package com.qys.livesMall.shop.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.esotericsoftware.minlog.Log;
import com.qys.livesMall.common.constants.Constants;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.common.result.R;
import com.qys.livesMall.common.utils.MessageUtils;
import com.qys.livesMall.finance.enums.AccountBusinessTypeEnum;
import com.qys.livesMall.finance.model.dto.FinancePayDTO;
import com.qys.livesMall.finance.service.FinanceBusinessService;
import com.qys.livesMall.framework.utils.SecurityUtils;
import com.qys.livesMall.product.entity.H2ProductSku;
import com.qys.livesMall.product.service.H2ProductSkuService;
import com.qys.livesMall.shop.constants.ShopConstant;
import com.qys.livesMall.shop.enums.ShopEventTypeEnum;
import com.qys.livesMall.shop.enums.ShopMessageEnum;
import com.qys.livesMall.shop.event.ShopEvent;
import com.qys.livesMall.shop.event.shop.pojo.ShopStocksPojo;
import com.qys.livesMall.shop.mapper.ShopReturnPurchaseMapper;
import com.qys.livesMall.shop.modal.dto.ShopReturnAuditDTO;
import com.qys.livesMall.shop.modal.dto.ShopReturnDTO;
import com.qys.livesMall.shop.modal.entity.*;
import com.qys.livesMall.shop.service.*;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author gmx
 * @since 2023-06-08
 */
@Service
public class ShopReturnPurchaseServiceImpl extends ServiceImpl<ShopReturnPurchaseMapper, ShopReturnPurchase> implements ShopReturnPurchaseService {

    @Autowired
    private H2ShopBaseService shopBaseService;
    @Resource
    private ShopGoodsSkuService shopGoodsSkuService;
    @Resource
    private ShopGoodsInfoService infoService;

    @Autowired
    private ShopPurchaseSkuService shopPurchaseSkuService;
    @Resource
    private H2ProductSkuService productSkuService;
    @Resource
    private ShopReturnApprovedService approvedService;

    @Resource
    private ShopGoodsSkuStocksService stocksService;

    @Autowired
    private FinanceBusinessService financeBusinessService;

    @Autowired
    private ApplicationContext applicationContext;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public R applyFor(ShopReturnDTO shopReturnDTO) {
        synchronized (shopReturnDTO.getShopGoodsId()){
            H2ShopBase shopBase = shopBaseService.queryShopBaseByUserId(SecurityUtils.getUserId());
            if (shopBase==null|| !Objects.equals(ShopConstant.ShopStatus.IN_BUSINESS,shopBase.getStatus())){
                throw new QysException(ShopMessageEnum.SHOP_NOT_EXIST);
            }
            //商品信息
            ShopGoodsInfo goodsInfo = infoService.getById(shopReturnDTO.getShopGoodsId());
            if(ObjectUtils.isEmpty(goodsInfo)){
                return R.fail(MessageUtils.message("system.error.goods.null"));
            }
            if (goodsInfo.isStatus()){
                return R.fail(MessageUtils.message("shop.order.goods"));
            }
            LambdaQueryWrapper<ShopGoodsSku> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ShopGoodsSku::getShopGoodsId,goodsInfo.getId());
            List<ShopGoodsSku> skus = shopGoodsSkuService.list(queryWrapper);
            List<Long> skuId = skus.stream().map(ShopGoodsSku::getId).collect(Collectors.toList());
//            for (Long id : skuId) {
//                count += orderSkuMapper.countOrderSkus(id);
//            }
//            if (count>0){
//                return R.fail(499, MessageUtils.message("still.orders"));
//            }
            //检查是否还有用户订单为支付

            //创建退货单
            ShopReturnApproved approved = new ShopReturnApproved();
            approved.setShopId(shopBase.getId());
            approved.setStatus(0);
            approved.setShopGoodsId(shopReturnDTO.getShopGoodsId());
            approved.setGoodsName(goodsInfo.getGoodsName());
            approved.setUserId(SecurityUtils.getUserId());
            approved.setUserName(SecurityUtils.getUsername());
            approved.setReturnReason(shopReturnDTO.getReturnReason());
            approved.setReasonDesc(shopReturnDTO.getReasonDesc());
            approved.setCreateTime(LocalDateTime.now());

            Integer num=0;
            BigDecimal amount=new BigDecimal("0");
            approvedService.save(approved);
            List<ShopReturnPurchase> rdb=new ArrayList<>();
            //查询库存
            for (ShopGoodsSku shopGoodsSku : skus) {
                LambdaQueryWrapper<ShopGoodsSkuStocks> stocksQueryWrapper = new LambdaQueryWrapper<>();
                stocksQueryWrapper.eq(ShopGoodsSkuStocks::getSkuId,shopGoodsSku.getId());
                stocksQueryWrapper.eq(ShopGoodsSkuStocks::getState,false);
                stocksQueryWrapper.gt(ShopGoodsSkuStocks::getNum,0);
                List<ShopGoodsSkuStocks> stocks = stocksService.list(stocksQueryWrapper);
                if (CollectionUtils.isEmpty(stocks)){
                    continue;
                }

                for (ShopGoodsSkuStocks stock : stocks) {
                    //获取到采购单
                    ShopReturnPurchase returnDetail=new ShopReturnPurchase();
                    returnDetail.setReturnId(approved.getId());
                    returnDetail.setSkuId(shopGoodsSku.getSkuId());
                    returnDetail.setStockId(stock.getId());
                    returnDetail.setShopId(stock.getShopId());
                    returnDetail.setPurchaseId(stock.getPurchaseId());
                    returnDetail.setGoodsSkuId(stock.getSkuId());
                    returnDetail.setGoodsSkuName(stock.getSkuName());
                    returnDetail.setNum(stock.getNum());
                    returnDetail.setPrice(stock.getPrice());
                    returnDetail.setPayType(Integer.valueOf(stock.getPayType()));
                    returnDetail.setTotalPrice(new BigDecimal("0"));
                    if (stock.getPayType().equals("1")){
                        LambdaQueryWrapper<ShopPurchaseSku> purchaseSkuQueryWrapper = new LambdaQueryWrapper<>();
                        ShopPurchaseSku shopPurchaseSku=shopPurchaseSkuService.getById(stock.getPurchaseId());
                        if (shopPurchaseSku==null){
                            return R.fail(MessageUtils.message("shop.order.null"));
                        }
                        BigDecimal money = shopPurchaseSku.getActualPrice().multiply(new BigDecimal(stock.getNum()));
                        returnDetail.setTotalPrice(money);
                        amount=amount.add(money);
                    }
                    num=num+returnDetail.getNum();
                    rdb.add(returnDetail);
                    stock.setNum(0);
                    boolean up=stocksService.upStockNum(stock,returnDetail.getNum());

                    if(!up)return R.fail(MessageUtils.message("goods.stocks.error"));
                }
            }
            if (!CollectionUtils.isEmpty(rdb)) {
                approved.setNum(num);
                approved.setAmount(amount);
                saveBatch(rdb);
                approvedService.updateById(approved);
            }else {
                approvedService.removeById(approved);
            }
            try {
                applicationContext.publishEvent(new ShopEvent(ShopEventInfo.builder()
                        .shopId(approved.getShopId())
                        .eventType(ShopEventTypeEnum.SHOP_STOCKS.getType())
                        .paramObj(ShopStocksPojo.builder()
                                .build()
                        )
                        .build())
                );
            } catch (Exception e) {
                Log.info("提现采购退货不通过监听异常,approved:[{}]", JSON.toJSONString(approved));
            }
            return R.ok();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R auditPass(ShopReturnAuditDTO auditDTO){
        synchronized (auditDTO.getId()){
            ShopReturnApproved approved=approvedService.getById(auditDTO.getId());
            if (approved==null){
                throw new QysException(MessageUtils.message("shop.order.null"));
            }
            if (!Objects.equals(approved.getStatus(), Constants.YesNoInt.NO)){
                throw new QysException(ShopMessageEnum.STATE_HAS_CHANGED);
            }
            approved.setOpinion(auditDTO.getAuditDesc());
            approved.setHandleUserId(SecurityUtils.getUserId());
            approved.setHandleUserName(SecurityUtils.getUsername());
            approved.setStatus(2);
            approved.setUpdateTime(LocalDateTime.now());
            //付款
            List<ShopReturnPurchase> list=listByReturnId(approved.getId());
            if (CollectionUtils.isEmpty(list)){
                throw new QysException(MessageUtils.message("shop.order.null"));
            }
            List<Long> purchaseIds=list.stream().map(ShopReturnPurchase::getPurchaseId).collect(Collectors.toList());
            List<ShopPurchaseSku> purchaseSkus=shopPurchaseSkuService.listByIds(purchaseIds);
            Map<Long,ShopPurchaseSku> map=purchaseSkus.stream().collect(Collectors.toMap(ShopPurchaseSku::getId, v->v));
            for (ShopReturnPurchase pur:list) {
                //退回库存
                H2ProductSku productSku=productSkuService.getById(pur.getSkuId());
                if (productSku==null){
                    continue;
                }
                synchronized (productSku.getId()){
                    Integer num=productSku.getNum()+pur.getNum();
                    productSku.setNum(num);
                    productSkuService.updateById(productSku);
                }
                if (Objects.equals(pur.getPayType(), Constants.YesNoInt.NO)){
                    continue;
                }
                FinancePayDTO payDTO = new FinancePayDTO();
                payDTO.setUserId(approved.getUserId());
                payDTO.setShopId(approved.getShopId());
                payDTO.setBusinessNo(map.get(pur.getPurchaseId()).getBusinessNo());
                payDTO.setAmountIncurred(pur.getTotalPrice());
                payDTO.setDescription(auditDTO.getAuditDesc());
                payDTO.setBusinessType(AccountBusinessTypeEnum.REFUND);
                financeBusinessService.pay(payDTO);

                if (!payDTO.getSuccess()) {
                    throw new QysException(payDTO.getMessage());
                }

            }
            approvedService.updateById(approved);
        }
        return R.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R auditNoPass(ShopReturnAuditDTO auditDTO){
        synchronized (auditDTO.getId()){
            ShopReturnApproved approved=approvedService.getById(auditDTO.getId());
            if (approved==null){
                throw new QysException(MessageUtils.message("shop.order.null"));
            }
            if (!Objects.equals(approved.getStatus(), Constants.YesNoInt.NO)){
                throw new QysException(ShopMessageEnum.STATE_HAS_CHANGED);
            }
            approved.setOpinion(auditDTO.getAuditDesc());
            approved.setHandleUserId(SecurityUtils.getUserId());
            approved.setHandleUserName(SecurityUtils.getUsername());
            approved.setStatus(1);
            //付款
            List<ShopReturnPurchase> list=listByReturnId(approved.getId());
            if (CollectionUtils.isEmpty(list)){
                throw new QysException(MessageUtils.message("shop.order.null"));
            }
            List<Long> stockIds=list.stream().map(ShopReturnPurchase::getStockId).collect(Collectors.toList());
            List<ShopGoodsSkuStocks> stocks=stocksService.listByIds(stockIds);
            Map<Long,ShopGoodsSkuStocks> map=stocks.stream().collect(Collectors.toMap(ShopGoodsSkuStocks::getId, v->v));
            for (ShopReturnPurchase pur:list) {
                ShopGoodsSkuStocks stock=map.get(pur.getStockId());
                Integer oldNum=stock.getNum();
                stock.setNum(oldNum+pur.getNum());
                boolean up=stocksService.upStockNum(stock,oldNum);
                if (!up){
                    throw new QysException(MessageUtils.message("stock.is.update.restart"));
                }
            }
            approvedService.updateById(approved);
            try {
                applicationContext.publishEvent(new ShopEvent(ShopEventInfo.builder()
                        .shopId(approved.getShopId())
                        .eventType(ShopEventTypeEnum.SHOP_STOCKS.getType())
                        .paramObj(ShopStocksPojo.builder()
                                .build()
                        )
                        .build())
                );
            } catch (Exception e) {
                Log.info("提现采购退货不通过监听异常,approved:[{}]", JSON.toJSONString(approved));
            }
        }

        return R.ok();
    }

    List<ShopReturnPurchase> listByReturnId(Long returnId){
        LambdaQueryWrapper<ShopReturnPurchase> qw=new LambdaQueryWrapper();
        qw.eq(ShopReturnPurchase::getReturnId,returnId);
        return list(qw);
    }

}
